Skip to content

feat: Add Pagination for server requests - #140

Open
denniskawurek wants to merge 13 commits into
modelcontextprotocol:mainfrom
denniskawurek:add-pagination
Open

feat: Add Pagination for server requests#140
denniskawurek wants to merge 13 commits into
modelcontextprotocol:mainfrom
denniskawurek:add-pagination

Conversation

@denniskawurek

@denniskawurek denniskawurek commented Apr 10, 2025

Copy link
Copy Markdown
Contributor

Adds the Pagination feature to the prompts/list feature to fulfil the specification.

Motivation and Context

This adds the Pagination feature to the prompts/list feature as described in the specification.

To make this possible mainly two changes are made:

  1. The logic for cursor handling is added.
  2. Handling for invalid parameters (MCP error code -32602 (Invalid params)) is added to the McpServerSession.

Decisions made:

  1. For now the cursor is the integer value of the start index encoded as a base64 string.
  2. The page size is set to 10.
  3. When parameters are found to be invalid the newly introduced McpParamsValidationError is returned to handle it properly in the McpServerSession.

If this change is ok, I'm happy to create a follow-up PR for the other MCP features. Maybe some parts of the cursor handling can be moved out to separate methods.

How Has This Been Tested?

Integration tests are added for the prompts/list feature.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Resolves #967

@denniskawurek
denniskawurek force-pushed the add-pagination branch 2 times, most recently from 4c05e1a to 8d48b93 Compare April 18, 2025 12:06

@chemicL chemicL left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution! It is a great start, would you like to take this further and unify the logic for other listing requests?

Comment thread mcp/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java Outdated
Comment thread mcp/src/main/java/io/modelcontextprotocol/spec/McpParamsValidationError.java Outdated
Comment thread mcp/src/main/java/io/modelcontextprotocol/spec/McpParamsValidationError.java Outdated
Comment thread mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java Outdated
Comment thread mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java Outdated
@chemicL chemicL added the waiting for user Waiting for user feedback or more details label Apr 23, 2025
@denniskawurek

Copy link
Copy Markdown
Contributor Author

Hi,

thanks for your review and your feedback!

Thank you for the contribution! It is a great start, would you like to take this further and unify the logic for other listing requests?

Yes I will do this. I should be able to update the pull request by the end of the week.

@denniskawurek
denniskawurek force-pushed the add-pagination branch 3 times, most recently from 3dce44d to 0c93c71 Compare April 26, 2025 14:52
@denniskawurek
denniskawurek requested a review from chemicL April 26, 2025 15:36
@denniskawurek

Copy link
Copy Markdown
Contributor Author

I did another push with small changes in the commit title and message and have also changed a few comments and names in tests. No business logic was affected.

@denniskawurek denniskawurek changed the title feat: Add Pagination for requesting list of prompts feat: Add Pagination for server requests Apr 29, 2025
@denniskawurek
denniskawurek force-pushed the add-pagination branch 3 times, most recently from 3718965 to 5f7bb9b Compare May 3, 2025 11:41
Adds the Pagination feature as described in the specification for
prompts, resources, resource templates and tools.

To make this possible mainly two changes are made:

1. The logic for cursor handling is added.
2. Handling for invalid parameters (MCP error code `-32602 (Invalid params)`) is added to the `McpServerSession`.

For now the cursor is the base64 encoded start index of the next page
and the hash value of the collection at time of computing.

The page size is set to 10.

When parameters are found to be invalid the newly introduced `McpParamsValidationError` is returned to handle it properly in the `McpServerSession`.
@tzolov tzolov removed the waiting for user Waiting for user feedback or more details label May 12, 2025
@pantanurag555

Copy link
Copy Markdown
Contributor

@denniskawurek Is this change still being worked on? I am making some changes to handle pagination on the client side and just saw that the server side changes are yet to be merged. I can pick up the remaining work on this PR if you need some help.

@denniskawurek

Copy link
Copy Markdown
Contributor Author

Hi @pantanurag555

I've just merged main into the branch, so that it's up to date, again.

Regarding your question I haven't started anything in regards of the client, yet.
The idea was here to have only the implementation for the server and implement the client in a separate commit/merge request, to keep the change as small as possible like it's stated in the contribution guidelines.
However that's the way I'd prefer to do.

Maybe @chemicL can give some information of the maintainer point of view and whether this change is interesting.

Regards
Dennis

@denniskawurek

Copy link
Copy Markdown
Contributor Author

Looks like the test is flaky somehow. However, I'm not allowed to rerun the job.

@lwilli

lwilli commented Oct 13, 2025

Copy link
Copy Markdown

Hi, thanks for putting this work together. I am very interested in seeing PR merged as it's blocking some of my work right now. What needs to be done to move this along? Thanks in advance!

@denniskawurek

Copy link
Copy Markdown
Contributor Author

Resolves #967

@Kehrlann Kehrlann left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @denniskawurek , picking this up from #967

A few concerns here:

  1. It's a breaking change ; we should default to non-paginated results
  2. Page size should be configurable
  3. We've introduced tool filtering as part of #1108 ; so now the view is request dependent. If that PR gets merged first, you'll need to adapt the pagination to happen after the filtering (shouldn't be too hard)

var cursor = paginatedRequest != null ? paginatedRequest.cursor() : null;

var mapSize = this.tools.size();
var mapHash = this.tools.hashCode();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is likely wrong across horizontally-scaled instances - hashCode hashes the *ToolSpecification, which contain handlers, and the hash of those will be tied to object identity.

Additionally, that's hashing a lot of things, including input and output schema strings, without ever caching them.

We should probably hash across keys (tool names), but I guess we have no guarantee of tool names being unique so there's something to do about this too

Comment on lines +600 to +601
var resultList = this.resources.values()
.stream()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the ordering is not guaranteed to be stable in a ConcurrentHashMap. I think in practice it's stable, BUT if you start adding elements dynamically and grow the underlying map, you may end up with different orders. I don't think it's a massive problem in this specific case.

If we do order by key as suggested in tools, we can sort the keys and get a stability guarantee (unless you modify the collection during a pagination run, but that's a corner case.)

Comment on lines +1562 to +1584
private BiFunction<McpSyncServerExchange, McpSchema.CallToolRequest, CallToolResult> buildCallToolRequestHandlerMock() {
var callResponse = McpSchema.CallToolResult.builder()
.addContent(McpSchema.TextContent.builder("CALL RESPONSE").build())
.build();

return (exchange, request) -> {
// perform a blocking call to a remote service
try {
HttpResponse<String> response = HttpClient.newHttpClient()
.send(HttpRequest.newBuilder()
.uri(URI.create(
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
.GET()
.build(), HttpResponse.BodyHandlers.ofString());
String responseBody = response.body();
assertThat(responseBody).isNotBlank();
}
catch (Exception e) {
e.printStackTrace();
}
return callResponse;
};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for reaching out to a remote service in tests? I'd rather avoid that and just return a result.

@Kehrlann Kehrlann self-assigned this Aug 26, 2026
@Kehrlann Kehrlann added enhancement New feature or request area/server P3 Nice to haves, rare edge cases waiting for user Waiting for user feedback or more details labels Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/server enhancement New feature or request P3 Nice to haves, rare edge cases waiting for user Waiting for user feedback or more details

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server should handle paginated requests

6 participants